#!/usr/bin/env python3
# -*- coding: utf-8 -*-
' main entry '
__author__ = 'pingwu you'

import asyncio
from types import MethodType
from ypp_base.oop.main import Weekday


def val_ref():
    var1=[1,2,3]
    var2=var1
    var2.append(6666)
    print(var1)
    print(var2)
    var3=(1,"a",[])
    var3[2].append(333)
    print(var3)
    try:  
        #不能再修改了！！！
        var3[2]=["66666"]
        print(var3)
    except BaseException as e:
        print(e)
    finally:
        print("excpthandle finish")
    
    dic1={"aa":"中国",11:999}
    print(dic1)
    try:
        #不可变对象就是指内容不可变的
        var33=[222]        
        #不可变对象（可hash的）作为key
        dic1={"aa":"中国",var33:999}
        print(dic1)        
    except BaseException as e:
        print(e)    
    try:
        #不可变对象就是指内容不可变的        
        #不可变对象（可hash的）作为key
        dic1={"aa":"中国",[]:999}
        print(dic1)
    except BaseException as e:
        print(e)    

def func11():
    from ypp_base.funs import main
    var1,var2 =main.ret_tuple()
    print(str(var1),str(var2))
    main.complex("必须",name1="1111111111")
    ls=[1,"abc","efg"]
    #位置参数只能按照位置进行匹配
    main.complex("必须",name1="1111111111",*ls)
    #kw中的name2会被映射到命名关键字参数上，被吃掉
    #kw中的关键字必须是字符串型
    kw={"name2":"abc","default":"00000","edf":"中国"}
    main.complex("必须",name1="1111111111",**kw)

    #位置参数有，keyvalue参数也有对应参数，则异常中断
    ls=[1,"abc","efg"] #ls中的参数会被位置参数吃掉
    #kw={"name2":"abc","default":"00000","edf":"中国"}
    kw={"name1":"111111","name2":"222222","edf":"中国"}
    main.complex(*ls,**kw)

def collect():
    from ypp_base.collects import main as collect
    collect.slice()
    collect.list_gen()
    gen=collect.genertor()
    while(True):
        try:
            #可以被next()函数调用并不断返回下一个值的对象称为迭代器：Iterator。
            #它们表示一个惰性计算的序列；
            v=next(gen)
            print(v)
        except StopIteration as e:
            #通过异常获取最后的返回结果
            print('Generator return value:', e.value)
            break
    #凡是可作用于for循环的对象都是Iterable类型；
    for x in collect.genertor():
        print(x)
    for x in ["aaa","bbb","ccc"]:
        print(x)
    #集合数据类型如list、dict、str等是Iterable但不是Iterator，不过可以通过iter()函数获得一个Iterator对象
    it = iter([1, 2, 3, 4, 5])
    while True:
        try:
            # 获得下一个值:
            x = next(it)
            print(x)
        except StopIteration:
            # 遇到StopIteration就退出循环
            break

def func22():
    from ypp_base.funs import main as func
    func.mapreduce()
    func.sort_help()
    func.clouse_global_arg="外部11111111"
    cs=func.closue_help("aaaaaa")
    cs()
    func.clouse_global_arg="外部222222222"
    cs=func.closue_help("bbbbbb")
    cs()

def oop11():
    from ypp_base.oop import main as oop
    print("类属性：%s"%oop.Animal.class_var)
    an=oop.Animal("猪","aaa","bbb")
    an.name="羊"
    #以一个下划线开头的实例变量名，比如_name，这样的实例变量外部是可以访问的，
    # 但是，按照约定俗成的规定，当你看到这样的变量时，意思就是，“虽然我可以被访问，但是，请把我视为私有变量，不要随意访问”。
    an._hello11="啊啊啊啊"
    #双下划线开头的实例变量是不是一定不能从外部访问呢？其实也不是。
    # 不能直接访问__name是因为Python解释器对外把__hello22变量改成了_Animal__hello22
    an.__hello22="八八八八八"
    #类似于js，可以动态附加属性！！！
    an.newname="动态附加的属性"
    an.run()
    print(dir(an))
    print(dir(object))

    dg=oop.Dog("小狗")
    dg.run()
    print(isinstance(dg,oop.Animal))
    print(type(dg))
    view_run(dg)    

def view_run(animal):
    from ypp_base.oop import main as oop
    if(animal != None):
        #if(isinstance(animal,oop.Animal)):
        #动态语言的“鸭子类型”，它并不要求严格的继承体系，一个对象只要“看起来像鸭子，走起路来像鸭子”，那它就可以被看做是鸭子。
        if(hasattr(animal,"run")):
            import types
            if(type(getattr(animal,"run"))==types.MethodType):
                print("开始执行吧---------------------")
                animal.run()

def oop22():
    from ypp_base.oop import main as oop  
    #类上动态添加实例方法
    oop.Cat.SAY= animal_say22
    cat=oop.Cat("小猫")    
    try:
        cat.newname="含糊糊"
    except BaseException as e:
        print(e)
    cat.run()
    #实例上动态添加方法，只当前实例有效
    cat.say=MethodType(animal_say,cat)
    cat.say("开卷考就看")
    cat.SAY("zk看见就看见")

    cat=oop.ChinaCat("小猫")    
    try:
        cat.newname="含糊糊"
    except BaseException as e:
        print(e)
    cat.run()    
    cat.SAY("zk看见就看见")

    cat.birth=10
    print(cat.age)
    print(cat)
    #链式调用，无属性则自动追加
    ch=oop.Chain().aaa.bbb.cccc.ddd
    print(ch)

    st=oop.Student("我是学生")
    print(callable(st))
    st()

    #枚举
    for name, member in oop.Wekday.__members__.items():
        print(name, '=>', member, ',', member.value)    
    for name, member in oop.Weekday.__members__.items():
        print(name, '=>', member, ',', member.value)    
    print(str(oop.Weekday.Tue)+"--"+str(oop.Weekday.Tue.value))
    
    #动态创建类型
    MyClass=type("MyClass",(object,),{"attr1":"中国","say":lambda self:print("say---"+self.attr1)})
    mobj=MyClass()
    print(mobj.attr1)
    mobj.say()

    #lambda 多行  包装成tuple,list,dict,set
    lbd=lambda x:(
        print(x),
        print("aaaa"),
        10)
    lbd("6666")

def animal_say(self,msg):
    print(self.name+":"+msg)
def animal_say22(self,msg):
    print(self.name+"（类类类）:"+msg)

def raise_demo():
    try:
        raise Exception("我自定义的异常啊")
    except BaseException as e:
        print(e)

def io_help():
    from ypp_base.io import help as iohelp
    iohelp.read_help()
    iohelp.stringio_help()
    iohelp.byteio_help()
    iohelp.os_help()
    iohelp.pikle_help()
    iohelp.json_help()

def mp_ipc_help():
    from ypp_base.multiprocess import help as mp_help
    mp_help.multi_help()
    mp_help.multi_pool()
    mp_help.outer_subp()
    mp_help.ipc_help()

def thread_help():
    from ypp_base.threads import help as th
    #th.start_thread()
    th.without_lock()
    th.with_lock()
    th.thread_local()

def net_socket_help():
    import sys    
    from ypp_base.net import help as net_io
    istcpclient=False
    if(len(sys.argv)>1):
       if(sys.argv[1]=="istcpclient"):
            istcpclient=True
    if(istcpclient):
        net_io.tcpclient()
    else:
        net_io.server()

def db_help():
    from ypp_base.db import sqllite
    #sqllite.init()
    sqllite.query()
    from ypp_base.db import mysql
    #mysql.init()
    mysql.query()
    mysql.trans()

def web_help():
    from ypp_app.web.wsgi_server import main as wsgi
    #wsgi.start_wsgiserv()
    from ypp_app.web.flask import main as flask
    flask.start_flask()

def aysnio_help():
    from ypp_base.io import coroutine_gen as cogen
    cogen.start_coruntine()
    cogen.handle_gen()
    from ypp_base.io import asyncio_help as ayio
    #ayio.start_evtloop(2)
    #ayio.start_evtloop(1,True)
    #ayio.start_evtloop222(1)
    #ayio.start_evtloop222(2)

    # from ypp_base.io import asyncio_new as ayio_new
    # ayio_new.start_evtloop(2)
    # ayio_new.start_evtloop(1,True)
    # ayio_new.start_evtloop222(1)
    # ayio_new.start_evtloop222(2)

    from ypp_base.io import aiohttp_help as aioweb
    aioweb.start_aiohttp()

def mixbase_help():
    from ypp_base.mixbase import datetime_help as dt
    dt.dt_help()
    from ypp_base.mixbase import collects_help as clh
    clh.help_demo()
    from ypp_base.mixbase import base64_help as b64
    b64.help_demo()
    from ypp_base.mixbase import hash_help as hh
    hh.help_demo()
    from ypp_base.mixbase import contextlib_help as cxth
    cxth.help_demo()
    from ypp_base.mixbase import urlreq_help as ureq
    #ureq.demo_help()
    #ureq.html_parse()
    #ureq.requests_help()
    from ypp_base.mixbase import chardetect_help as csdh
    csdh.demo_help()
    from ypp_base.aiomysql import main as aiomysql
    #aiomysql.start_handle()

    #相对位置附加一些模块搜索路径，而不是绝对位置（不便于程序的位置迁移）
    import sys
    from os.path import abspath, join, dirname
    #join 能自动使用当前系统的路径分割符进行组合拼接
    sys.path.insert(0, join(abspath(dirname(__file__)), 'src'))
    print(sys.path)  


"""
生成器/协程/异步方法async await
"""
def demo_gen111():
    yield "aaaa"

def demo_gen222():
    n=yield "bbbb"
    return "CCCCCCCCCCCCCCCCCCCCCCCCCCCC--"+str(n)

#协程类型
#print(type(async_function()) is types.CoroutineType)
async def async_function():
    return "我是协程async_function的返回值"

#异步生成器类型
#print(type(async_generator()) is types.AsyncGeneratorType)
async def async_generator():
    yield "async_generator返回值111111"
    yield "async_generator返回值222222"
    #不能在异步生成器中直接return 任何具体值
    return

async def async_function222():
    #需要消息循环
    #await asyncio.sleep(5)
    """
    await后面的对象需要是一个Awaitable，或者实现了相关的协议
    实现了__await__方法  def __await__(self):  yield
    Coroutine类(async)也继承了Awaitable，而且实现了send，throw和close方法
    """
    res = await async_function()
    #async for语法表示我们要后面【迭代】的是一个异步生成器
    async for res2 in async_generator():
        res+="  异步生成器迭代："+res2
    return "我是协程async_function222的返回值----嵌套执行的："+str(res)

def run_cor(coroutine):
    try:
        coroutine.send(None)
    except StopIteration as e:
        return e.value

def run_cor222(coroutine):
    try:
        next(coroutine)
    except StopIteration as e:
        return e.value

def demo_aiogo():
    try:
        g1=demo_gen111()
        print(g1.send(None))
        print("----1111111-----")
        print(g1.send(2))
        print("----2222222-----")
        print(g1.send(2))
    except BaseException as e:
        print("发生异常了111111---"+str(e)+"--"+str(type(e)))
    
    try:
        g1=demo_gen222()
        print(g1.send(None))
        print("----333333-----")
        print(g1.send(2))
        print("----444444-----")
        print(g1.send(2))
    except BaseException as e:
        print("发生异常了222222---"+str(e)+"--"+str(type(e)))

    try:
        g1=demo_gen222()
        print("----555555-----")
        for x in g1:#屏蔽了stop异常，只返回yield值
            print(x)        
    except BaseException as e:
        print("发生异常了33333333---"+str(e)+"--"+str(type(e)))

    try:
        g1=demo_gen222()
        print("----6666666-----")
        print(next(g1))
        print(next(g1))
    except BaseException as e:
        print("发生异常了4444---"+str(e)+"--"+str(type(e)))
    
    #这些都是同步关联触发，如果有异步io就必须有消息循环了！！！
    print(run_cor(async_function()))
    print(run_cor(async_function222()))   
    
    """
    只能用send(None)进行触发，不能用next(coruntine)进行触发
    """
    # print(run_cor222(async_function()))
    # print(run_cor222(async_generator()))

if(__name__=="__main__"):
    print("非模块进来的啊")
    from ypp_base.log.main import getLogger
    import os
    logger=getLogger(os.path.dirname(__file__)+"/log/log.log")
    logger.debug('debug')
    logger.info('info')
    logger.warning('warning')
    logger.error('error')
    logger.critical('critical')


    val_ref()
    from ypp_base.str.help import lower
    print(lower("ABCDEF"))
    from ypp_app.hello.main import hello_world
    hello_world()
    func11()
    collect()
    func22()
    oop11()    
    oop22()
    raise_demo()
    import pdb
    #单步调试 python -m pdb main.py
    var=100
    #直接运行后自动停止
    #pdb.set_trace()
    var+=2

    from ypp_base.str.help import re_help
    re_help()

    #io_help()
    #mp_ipc_help()
    #thread_help()
    
    #由于window下 进程间共享数据对象pinkle序列化问题，暂时不执行了
    # from ypp_base.multiprocess import help as mhelp
    # import sys    
    # if(hasattr(sys.argv,"isworker")):
    #     mhelp.dist_worker()
    # else:
    #     mhelp.dist_master()

    #from ypp_base.net import help as net_io
    #net_io.help111()
    #net_socket_help()   
    
    #db_help()
    #web_help()

    #aysnio_help()
    
    mixbase_help()
    demo_aiogo()